#pragma once 

#include <sw/redis++/redis.h>
#include <iostream>

#include "logger.hpp"

namespace xu
{
    class RedisClientFactory
    {
    public:
        using ptr = std::shared_ptr<RedisClientFactory>;
        static std::shared_ptr<sw::redis::Redis> Create(const std::string &ip ,
            int port,int db, bool keep_alive)
        {
            std::shared_ptr<sw::redis::Redis> res;
            try 
            {
                sw::redis::ConnectionOptions opts;
                opts.host = ip;
                opts.port = port;
                opts.db = db;
                opts.keep_alive = keep_alive;
                res = std::make_shared<sw::redis::Redis>(opts);
            } 
            catch (const sw::redis::Error& e) 
            {
                LOG_ERROR("Redis连接失败: {}",e.what());
                return std::shared_ptr<sw::redis::Redis>();
            }

            return res; 
        }
    };

    class Session
    {
    public:
        using ptr = std::shared_ptr<Session>;
        Session(const std::shared_ptr<sw::redis::Redis> & client)
        :_client(client)
        {}
        void Append(const std::string& sid,const std::string& uid)
        {
            _client->set(sid,uid);
        }
        void Remove(const std::string& sid)
        {
            _client->del(sid);
        }
        sw::redis::OptionalString GetUid(const std::string& sid)
        {
            return _client->get(sid);
        }
    private:
        std::shared_ptr<sw::redis::Redis> _client;
    };

    class Status
    {
    public:
        using ptr = std::shared_ptr<Status>;
        Status(const std::shared_ptr<sw::redis::Redis> & client)
        :_client(client)
        {}
        void Append(const std::string& uid)
        {
            _client->set(uid,"");
        }
        void Remove(const std::string& uid)
        {
            _client->del(uid);
        }
        bool Exist(const std::string& uid)
        {
            auto res =  _client->get(uid);
            if(res) return true;
            return false;
        }
    private:
        std::shared_ptr<sw::redis::Redis> _client; 
    };

    class Codes
    {
    public:
        using ptr = std::shared_ptr<Codes>;
        Codes(const std::shared_ptr<sw::redis::Redis> & client)
        :_client(client)
        {}
        void Append(const std::string& cid,const std::string &code,
            std::chrono::milliseconds t = std::chrono::milliseconds(60000))
        {
            _client->set(cid,code,t);
        }
        void Remove(const std::string& cid)
        {
            _client->del(cid);
        }
        sw::redis::OptionalString GetCode(const std::string& cid)
        {
            return   _client->get(cid);
        }
    private:
        std::shared_ptr<sw::redis::Redis> _client; 
    };
}